<template>
  <div class="app-container ">
    <FilterSearch v-show="showSearch" class="filter-search" :value="queryParams" :config="configData">
    </FilterSearch>
    <RightToolbar v-model:showSearch="showSearch"></RightToolbar>
    <div class="main">
      <div class="table">
        <el-table v-loading="tableData.loading" :data="tableData.rows" row-key="menuId"
          :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" ref="tableRef">
          <el-table-column type="index" label="序号" minWidth="60">
            <template #default="scope">
              {{ scope.$index + 1 }}
            </template>
          </el-table-column>
          <el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" minWidth="160"></el-table-column>
          <el-table-column prop="icon" label="图标" align="center" minWidth="120">
            <template #default="scope">
              <svg-icon :icon-class="scope.row.icon" />
            </template>
          </el-table-column>
          <el-table-column prop="menuType" label="菜单类型" sortable minWidth="120">
            <template #default="scope">
              <el-tag type="success" v-if="scope.row.menuType == 'M'">目录</el-tag>
              <el-tag v-else-if="scope.row.menuType == 'C'">菜单</el-tag>
              <el-tag type="warning" v-else>按钮</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="menuSort" label="排序" sortable minWidth="80"></el-table-column>
          <el-table-column prop="name" label="权限标识" :show-overflow-tooltip="true" minWidth="120"></el-table-column>
          <el-table-column prop="path" label="路由地址" :show-overflow-tooltip="true" minWidth="180"></el-table-column>
          <el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true" minWidth="160"></el-table-column>
          <el-table-column prop="status" label="状态" minWidth="80">
            <template #default="scope">
              <dict-tag :options="statusOptions" :value="scope.row.status"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column prop="hidden" label="显示状态" minWidth="80">
            <template #default="scope">
              <dict-tag :options="hiddenOptions" :value="scope.row.hidden"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column prop="alwaysShow" label="是否嵌套显示" minWidth="120">
            <template #default="scope">
              <dict-tag :options="whetherOptions" :value="scope.row.alwaysShow"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column prop="noCache" label="是否缓存" minWidth="80">
            <template #default="scope">
              <dict-tag :options="noCacheOptions" :value="scope.row.noCache"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column prop="breadcrumb" label="导航栏" minWidth="80">
            <template #default="scope">
              <dict-tag :options="hiddenOptions" :value="scope.row.breadcrumb"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column prop="status" label="导航栏操作" minWidth="120">
            <template #default="scope">
              <el-tag type="success" v-if="scope.row.affix == 1">删除</el-tag>
              <el-tag type="info" v-else>禁止删除</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="isFrame" label="是否外链" minWidth="80">
            <template #default="scope">
              <dict-tag :options="whetherOptions" :value="scope.row.isFrame"></dict-tag>
            </template>
          </el-table-column>
          <el-table-column label="备注" align="center" prop="remark" minWidth="200" :show-overflow-tooltip="true">
          </el-table-column>
          <el-table-column label="创建时间" align="center" sortable minWidth="180" prop="createTime">
          </el-table-column>
          <el-table-column label="更新时间" align="center" sortable minWidth="180" prop="updateTime">
          </el-table-column>
          <el-table-column label="操作" align="center" fixed="right" minWidth="240"
            class-name="small-padding fixed-width">
            <template #default="scope">
              <el-button size="mini" type="text" icon="Edit" v-hasPermi="['system:menu:edit']"
                @click="handleEdit(scope.row)">编辑</el-button>
              <el-button size="mini" type="text" icon="Plus" v-hasPermi="['system:menu:add']"
                @click="handleAdd(scope.row)">新增</el-button>
              <el-button size="mini" type="text" icon="Delete" v-hasPermi="['system:menu:remove']"
                @click="handleRemove(scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- 添加或编辑菜单对话框 -->
    <el-dialog :title="title" v-model="diaVis" width="880px" :close-on-click-modal="false">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="上级菜单">
              <el-tree-select v-model="form.parentId" ref="menuTreeRef" node-key="menuId" :data="formList.menuOptions"
                :props="{ label: 'menuName', children: 'children' }" @node-click="nodeClick"
                :render-after-expand="false" :disabled="form.menuType == 'M'" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单名称" prop="menuName">
              <el-input v-model="form.menuName" clearable placeholder="请输入菜单名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单类型">
              <el-radio-group v-model="form.menuType" @change="handleRadio" :disabled="formInline.title == '编辑'">
                <el-radio label="M">目录</el-radio>
                <el-radio label="C">菜单</el-radio>
                <el-radio label="F">按钮</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单图标">
              <el-popover placement="bottom-start" :width="540" v-model="formInline.showChooseIcon" trigger="click">
                <template #reference>
                  <el-input v-model="form.icon" placeholder="点击选择图标" @click="showSelectIcon" @blur="hideSelectIcon">
                    <template #prefix>
                      <svg-icon v-if="form.icon" :icon-class="form.icon" class="el-input__icon"
                        style="height: 32px;width: 16px;" />
                      <el-icon v-else style="height: 32px;width: 16px;">
                        <search />
                      </el-icon>
                    </template>
                  </el-input>
                </template>
                <icon-select ref="iconSelectRef" @clickWindow="closeWindow" @selected="selected"
                  :active-icon="form.icon" />
              </el-popover>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="高亮显示菜单名称" prop="activeMenu">
              <el-input v-model="form.activeMenu" clearable placeholder="请输入高亮显示菜单名称" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="路由地址">
              <template #label>
                <span>
                  <el-tooltip content="访问的路由地址，如：`user`，如外网地址需内链访问则以`http(s)://`开头" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  路由地址
                </span>
              </template>
              <el-input v-model="form.path" clearable placeholder="请输入路由地址,父组件需要加/前缀,子组件不能加/前缀" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="组件路径">
              <el-input v-model="form.component" clearable :disabled="form.menuType == 'M'"
                placeholder="请输入组件路径,例如(system/menu),如果是目录一律写为(Layout)" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="权限标识" prop="name">
              <el-input v-model="form.name" clearable placeholder="请输入权限标识" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="重定向">
              <el-input v-model="form.redirect" clearable placeholder="请输入重定向标识" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="显示排序">
              <el-input-number v-model="form.menuSort" controls-position="right" :min="0" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
                    <el-icon><question-filled /></el-icon> </el-tooltip>是否外链
                </span>
              </template>
              <el-radio-group v-model="form.isFrame">
                <el-radio :label="item.value" v-for="(item, index) in whetherOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="选择停用则路由将不会出现在侧边栏，也不能被访问" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  状态
                </span>
              </template>
              <el-radio-group v-model="form.status">
                <el-radio :label="item.value" v-for="(item, index) in statusOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="选择隐藏则路由将不会出现在侧边栏，但仍然可以访问" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  显示状态
                </span>
              </template>
              <el-radio-group v-model="form.hidden">
                <el-radio :label="item.value" v-for="(item, index) in hiddenOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="是否显示下级" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  显示下级
                </span>
              </template>
              <el-radio-group v-model="form.alwaysShow">
                <el-radio :label="item.value" v-for="(item, index) in whetherOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="是否缓存页面组件" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  缓存页面组件
                </span>
              </template>
              <el-radio-group v-model="form.noCache">
                <el-radio :label="item.value" v-for="(item, index) in noCacheOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="导航栏是否记录" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  导航栏记录
                </span>
              </template>
              <el-radio-group v-model="form.breadcrumb">
                <el-radio :label="item.value" v-for="(item, index) in hiddenOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="">
              <template #label>
                <span>
                  <el-tooltip content="是否在导航栏可删除" placement="top">
                    <el-icon><question-filled /></el-icon>
                  </el-tooltip>
                  导航栏可删除
                </span>
              </template>
              <el-radio-group v-model="form.affix">
                <el-radio :label="item.value" v-for="(item, index) in whetherOptions" :key="index">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="备注">
              <el-input v-model="form.remark" rows="3" resize="none" type="textarea" placeholder="请输入内容"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, toRefs } from "vue";
import IconSelect from "@/components/IconSelect";
import { handleTree } from "@/utils/ruoyi";
import { menuList, menuAdd, menuEdit, menuRemove } from "@/api/system/menu";
import { statusOptions, whetherOptions, hiddenOptions, noCacheOptions } from "@/constant";

const { proxy } = getCurrentInstance();
const tableData = reactive({
  rows: [],
  loading: false
});
const showSearch = ref(true);
const queryParams = ref({
  menuName: "",
  status: null,
  createTime: [],
});
const tableRef = ref(null);
const tableStatus = ref(false);
const formRef = ref(null);
const iconSelectRef = ref(null);

const formInline = reactive({
  diaVis: false,
  title: "新增",
  showChooseIcon: false,
  form: {
    menuId: null,
    parentId: null,
    menuName: "",
    icon: "",
    path: "",
    component: "Layout",
    menuSort: 0,
    redirect: "",
    status: 1,
    hidden: 1,
    noCache: 2,
    alwaysShow: 2,
    breadcrumb: 1,
    affix: 1,
    menuType: "M",
    isFrame: 2,
    name: "",
    remark: ""
  }
})
const { diaVis, title, showChooseIcon, form } = toRefs(formInline);
const formList = reactive({
  menuOptions: [
    {
      menuName: "xxx",
      children: [
        {
          menuName: "123",
        },
        {
          menuName: "456"
        }
      ]
    }
  ],
});
const configData = computed(() => {
  let config = {
    itemConfig: [
      {
        type: "input",
        prop: "menuName",
        label: "菜单名称",
        placeholder: "请输入"
      },
      {
        type: "select",
        prop: "status",
        label: "状态",
        placeholder: "请选择",
        optList: statusOptions
      },
      {
        type: "datetimerange",
        prop: "createTime",
        label: "创建时间",
        dateFormate: "YYYY-MM-DD HH:mm:ss",
        placeholder: "请选择"
      },
    ],
    operate: [
      {
        icon: "Search",
        type: "primary",
        name: "查询",
        handleClick: getLoad,
        rule: false,
      },
      {
        icon: "RefreshRight",
        type: "info",
        name: "重置",
        handleClick: reset,
        rule: false,
      },
      {
        icon: "Plus",
        type: "success",
        name: "新增",
        handleClick: insert,
        rule: false,
        disabled: !proxy.$auth.hasPermi("system:menu:add")
      },
      {
        icon: "Plus",
        type: "warning",
        name: "展开/折叠",
        handleClick: toggle,
        rule: false,
      }
    ],
    rules: {},
  };
  return config;
});
const rules = computed(() => {
  let rules = {
    menuName: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
    name: [{ required: true, message: "请输入权限标识", trigger: "blur" }],
  };
  return rules;
})
function hideSelectIcon(event) {
  var elem = event.relatedTarget || event.srcElement || event.target || event.currentTarget;
  var className = elem.className;
  if (className == "el-input__inner" && elem.placeholder != "请输入图标名称") {
    formInline.showChooseIcon = false;
  }
}
function showSelectIcon() {
  iconSelectRef.value.reset();
  formInline.showChooseIcon = true;
}
function selected(name) {
  formInline.form.icon = name;
  formInline.showChooseIcon = false;
}
function closeWindow() {
  setTimeout(() => {
    formInline.showChooseIcon = false;
  }, 100);
}
function toggle() {
  if (tableStatus.value) {
    tableData.rows.forEach(row => {
      tableRef.value.toggleRowExpansion(row, false);
    });
    tableStatus.value = !tableStatus.value;
    return;
  }
  tableData.rows.forEach(row => {
    tableRef.value.toggleRowExpansion(row, true)
  });
  tableStatus.value = !tableStatus.value;
}

const insert = () => {
  formInline.title = "新增";
  formInline.diaVis = true;
}
function handleEdit(row) {
  formInline.form = {
    id: row.id,
    menuId: row.menuId,
    parentId: row.parentId,
    menuName: row.menuName,
    activeMenu: row.activeMenu,
    icon: row.icon,
    path: row.path,
    component: row.component,
    menuSort: row.menuSort,
    status: row.status,
    hidden: row.hidden,
    noCache: row.noCache,
    alwaysShow: row.alwaysShow,
    breadcrumb: row.breadcrumb,
    affix: row.affix,
    redirect: row.redirect,
    menuType: row.menuType,
    isFrame: row.isFrame,
    name: row.name,
    remark: row.remark
  }
  formInline.title = "编辑";
  formInline.diaVis = true;
};
function submitForm() {
  formRef.value.validate(valid => {
    if (valid) {

      if (formInline.form.menuType == "C") {
        if (formInline.form.parentId == 0 || formInline.form.parentId == null) {
          return proxy.$modal.msg("请选择上级菜单");
        }
      }
      if (formInline.title == "新增") {
        menuAdd(formInline.form).then(res => {
          if (res.code == 200) {
            cancel();
            getLoad();
          }
        });
      } else {
        if (formInline.form.menuId == formInline.form.parentId) {
          return proxy.$modal.msg("上级菜单选择失败");
        }
        menuEdit(formInline.form).then(res => {
          if (res.code == 200) {
            cancel();
            getLoad();
          }
        });
      }
    };
  })
}
function handleAdd(row) {
  formInline.form.parentId = row.menuId;
  if (row.menuType == "M") {
    formInline.form.menuType = "C";
    formInline.form.component = "";
  } else if (row.menuType == "C") {
    formInline.form.menuType = "F";
  } else {
    return proxy.$modal.msg("按钮禁止新增");
  }
  formInline.title = "新增";
  formInline.diaVis = true;
};
function nodeClick(node) {
  formInline.form.parentId = node.menuId;
}
/** 删除按钮操作 */
function handleRemove(row) {
  proxy.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项？').then(() => {
    menuRemove(row.id).then(res => {
      getLoad();
      proxy.$modal.msgSuccess(res.data.msg);
    })
  });
}
const cancel = () => {
  formRef.value.resetFields();
  formInline.form = {
    menuId: null,
    parentId: null,
    menuName: "",
    icon: "",
    path: "",
    component: "Layout",
    menuSort: 0,
    redirect: "",
    status: 1,
    hidden: 1,
    noCache: 2,
    alwaysShow: 2,
    breadcrumb: 1,
    affix: 1,
    menuType: "D",
    isFrame: 2,
    name: "",
    remark: ""
  }
  formInline.title = "新增";
  formInline.diaVis = false;
}

function handleRadio(val) {
  if (val == "D") {
    formInline.form.parentId = null;
    formInline.form.component = "Layout";
    formInline.form.alwaysShow = 1;
  } else {
    formInline.form.component = "";
  }
}
const getLoad = () => {
  tableData.loading = true;
  menuList(queryParams.value).then(res => {
    tableData.rows = handleTree(res.data, "menuId");
    tableData.loading = false;
    getOptions();
  });
}
function getOptions() {
  menuList().then(res => {
    formList.menuOptions = [];
    let menu = { menuId: 0, menuName: '主类目', children: [] }
    menu.children = handleTree(res.data, "menuId");
    formList.menuOptions.push(menu);
  })
}
const reset = () => {
  queryParams.value = {
    menuName: "",
    status: null,
    createTime: []
  }
  getLoad();
}
onMounted(() => {
  getLoad();
})
</script>